package com.redisdatastorage.config;

import com.redisdatastorage.enums.RedisMode;
import io.micrometer.core.instrument.util.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedissonConfig {

    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public RedissonClient redissonClient() {
        Config config = standaloneConfig();
        if (RedisMode.CLUSTER.getMode().equals(redisProperties.getMode())) {
            config = clusterConfig();
        } else if (RedisMode.SENTINEL.getMode().equals(redisProperties.getMode())) {
            config = sentinelConfig();
        }
        return Redisson.create(config);
    }

    /**
     * 单机
     */
    public Config standaloneConfig() {
        Config config = new Config();
        String node = redisProperties.getHost() + ":" + redisProperties.getPort();
        node = node.startsWith("redis://") ? node : "redis://" + node;
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(node)
                .setTimeout(redisProperties.getTimeout());
        if (StringUtils.isNotBlank(redisProperties.getPassword())) {
            serverConfig.setPassword(redisProperties.getPassword());
        }
        return config;
    }

    /**
     * 集群模式
     */
    public Config clusterConfig() {
        Config config = new Config();
        List<String> nodes = new ArrayList<>();
        redisProperties.getCluster().getNodes().forEach(node -> nodes.add(node.startsWith("redis://") ? node : "redis://" + node));
        ClusterServersConfig serverConfig = config.useClusterServers()
                .setReadMode(redisProperties.getCluster().getReadMode())
                .addNodeAddress(nodes.toArray(new String[0]));
        if (StringUtils.isNotBlank(redisProperties.getPassword())) {
            serverConfig.setPassword(redisProperties.getPassword());
        }
        return config;
    }

    /**
     * 哨兵模式
     */
    public Config sentinelConfig() {
        Config config = new Config();
        List<String> nodes = new ArrayList<>();
        redisProperties.getSentinel().getNodes().forEach(node -> nodes.add(node.startsWith("redis://") ? node : "redis://" + node));

        SentinelServersConfig serverConfig = config.useSentinelServers()
                .addSentinelAddress(nodes.toArray(new String[0]))
                .setMasterName(redisProperties.getSentinel().getMaster())
                .setReadMode(redisProperties.getCluster().getReadMode())
                .setTimeout(redisProperties.getTimeout());
        if (StringUtils.isNotBlank(redisProperties.getPassword())) {
            serverConfig.setPassword(redisProperties.getPassword());
        }
        return config;
    }
}
